﻿using AutoMapper;
using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Extensions;
using QYmall.Core.Common.Helper;
using QYmall.Core.DBFactory.Database;
using QYmall.Core.IServices;
using QYmall.Core.Model.Models;
using QYmall.Core.Model.ViewModels;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace QYmall.Core.Services
{
    /// <summary>
    /// 优惠券接口实现
    /// </summary>
    public class ShopCouponService : BaseService, IShopCouponService
    {
        private readonly IUserService _userService;
        private readonly IMapper _mapper;

        public ShopCouponService(IDbContextFactory contentFactory,
            IUserService userService, IMapper mapper) : base(contentFactory)
        {
            _userService = userService;
            _mapper = mapper;
        }

        /// <summary>
        /// 查询一条记录
        /// </summary>
        public async Task<ShopCoupon?> QueryAsync(Expression<Func<ShopCoupon, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = await _context.Set<ShopCoupon>()
                .Include(x => x.Merchant)
                .Include(x => x.GoodsRelations).ThenInclude(t => t.Goods)
                .FirstOrDefaultAsync(funcWhere);
            return result;
        }

        /// <summary>
        /// 查询指定数量列表
        /// </summary>
        public async Task<IEnumerable<ShopCoupon>> QueryListAsync(int top, Expression<Func<ShopCoupon, bool>> funcWhere,
            string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = _context.Set<ShopCoupon>()
                .Include(x => x.Merchant)
                .Include(x => x.GoodsRelations)
                .Where(funcWhere).OrderByBatch(orderBy);//调用Linq扩展类进行排序
            if (top > 0) result = result.Take(top);//等于0显示所有数据
            return await result.ToListAsync();
        }

        /// <summary>
        /// 查询分页列表
        /// </summary>
        public async Task<PaginationList<ShopCoupon>> QueryPageAsync(int pageSize, int pageIndex, Expression<Func<ShopCoupon, bool>> funcWhere,
            string orderBy, WriteRoRead writeAndRead = WriteRoRead.Read)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var result = _context.Set<ShopCoupon>()
                .Include(x => x.Merchant)
                .Include(x => x.GoodsRelations)
                .Where(funcWhere).OrderByBatch(orderBy);//调用Linq扩展类排序
            return await PaginationList<ShopCoupon>.CreateAsync(pageIndex, pageSize, result);
        }

        /// <summary>
        /// 添加一条记录
        /// </summary>
        public async Task<ShopCouponDto> AddAsync(ShopCouponEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var goodsIds = modelDto.GoodsRelations.Select(x => x.GoodsId);
            var goodsList = await _context.Set<ShopGoods>().Where(x => goodsIds.Contains(x.Id)).ToListAsync();
            if (goodsList != null && goodsIds.Except(goodsList.Select(x => x.Id)).Count() > 0)
            {
                throw new ResponseException("商品列表有误，请检查后操作");
            }
            //映射成实体
            var model = _mapper.Map<ShopCoupon>(modelDto);
            model.AddBy = await _userService.GetUserNameAsync();
            model.AddTime = DateTime.Now;
            //保存
            await _context.Set<ShopCoupon>().AddAsync(model);
            var result = await this.SaveAsync();
            if (!result)
            {
                throw new ResponseException("数据保存时发生意外错误");
            }
            //映射成DTO
            return _mapper.Map<ShopCouponDto>(model);
        }

        /// <summary>
        /// 修改一条记录
        /// </summary>
        public async Task<bool> UpdateAsync(long id, ShopCouponEditDto modelDto, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            //检查类别或商品是否正确
            var goodsIds = modelDto.GoodsRelations.Select(x => x.GoodsId);
            var goodsList = await _context.Set<ShopGoods>().Where(x => goodsIds.Contains(x.Id)).ToListAsync();
            if (goodsList != null && goodsIds.Except(goodsList.Select(x => x.Id)).Count() > 0)
            {
                throw new ResponseException("商品列表有误，请检查后操作");
            }
            //根据ID获取记录
            var model = await _context.Set<ShopCoupon>().Where(x => x.Id == id)
                .Include(x => x.GoodsRelations)
                .FirstOrDefaultAsync();
            //如果不存在则抛出异常
            if (model == null)
            {
                throw new ResponseException("数据不存在或已删除", ErrorCode.NotFound, StatusCodes.Status404NotFound);
            }
            //将DTO映射到源数据
            var mapModel = _mapper.Map(modelDto, model);
            //设置更新人和更新时间
            mapModel.UpdateBy = await _userService.GetUserNameAsync();
            mapModel.UpdateTime = DateTime.Now;
            //保存
            _context.Set<ShopCoupon>().Update(mapModel);
            var result = await this.SaveAsync();
            return result;
        }

        /// <summary>
        /// 根据条件删除记录
        /// </summary>
        public async Task<bool> DeleteAsync(Expression<Func<ShopCoupon, bool>> funcWhere, WriteRoRead writeAndRead = WriteRoRead.Write)
        {
            _context = _contextFactory.CreateContext(writeAndRead);//连接数据库

            var list = await _context.Set<ShopCoupon>()
                .Include(x => x.GoodsRelations)
                .Where(funcWhere).ToListAsync();
            if (list == null)
            {
                return false;
            }
            foreach (var modelt in list)
            {
                //删除优惠券历史记录
                var historyList = await _context.Set<ShopCouponHistory>().Where(x => x.CouponId == modelt.Id).ToListAsync();
                if (historyList != null)
                {
                    _context.Set<ShopCouponHistory>().RemoveRange(historyList);
                }
                //加入追踪列表
                _context.Set<ShopCoupon>().Attach(modelt);
            }
            //删除优惠券
            _context.Set<ShopCoupon>().RemoveRange(list);

            return await this.SaveAsync();
        }

    }
}
